package org.basket;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.basket.core.BasketMessage;
import org.basket.core.BasketUser;
import org.basket.core.DBManager;
import org.basket.core.DBManager.DayRecord;
import org.basket.core.UIManager;
import org.basket.core.UIManager.Page;
import org.basket.xml.XML;

public class BasketschedulerServlet extends HttpServlet {

	private static final long serialVersionUID = 5735703455575127586L;

	static {
		UIManager.addPage(BasketschedulerServlet.class);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		response.setContentType("text/html; charset=utf-8");
		final PrintWriter writer = response.getWriter();
		final Page page = UIManager.getPage(this.getClass());

		Calendar today = Calendar.getInstance();
		Calendar currdate = Calendar.getInstance();
		final String year = request.getParameter("year");
		final String mon = request.getParameter("mon");
		final String day = request.getParameter("day");

		page.setVar("year", year == null ? "" : year);
		page.setVar("mon", mon == null ? "" : mon);
		page.setVar("day", day == null ? "" : day);

		try {
			Calendar cal = Calendar.getInstance();
			cal.clear();
			cal.set(Integer.parseInt(year), Integer.parseInt(mon) - 1, Integer.parseInt(day));
			currdate = cal;
		} catch (Exception e) {
			// not interested in wrong dates - use current date
		}

		final String action = request.getParameter("action");
		final String mail = request.getParameter("mail");
		final String posttext = request.getParameter("posttext");
		final boolean presence = year == null || !isNullOrEmpty(request.getParameter("presence"));
		final boolean ball = presence && !isNullOrEmpty(request.getParameter("ball"));
		page.setVar("mail", mail == null ? "" : XML.escape(mail));
		page.setVar("posttext", XML.escape(posttext));
		page.setVar("presence", presence ? "checked" : "");
		page.setVar("ball", ball ? "checked" : "");

		final String fmail = request.getParameter("fmail");
		final String fname = request.getParameter("fname");
		page.setVar("fmail", fmail == null ? "" : fmail);
		page.setVar("fname", fname == null ? "" : fname);

		if ("addpost".equals(action)) {

			if (mail != null && mail.length() > 0) {
				final String userName = DBManager.getUserName(mail);

				if (userName != null) {
					final String currentDate = DBManager.formatDate(currdate);
					List<BasketMessage> dayMessages = DBManager.getDayMessages(currentDate);
					if (dayMessages.size() <= 0) {
						DBManager.sendMailToAll(currentDate);
					}

					if (!isNullOrEmpty(posttext)) {
						BasketMessage message = new BasketMessage(currentDate, mail, presence, presence & ball, posttext, userName);
						DBManager.store(message);
					} else {
						BasketMessage message = new BasketMessage(currentDate, mail, false, false, posttext, userName);
						DBManager.delete(message);
					}
				}
			}

		} else if ("addfriend".equals(action)) {

			if (!isNullOrEmpty(mail) && !isNullOrEmpty(fmail)) {

				if (isNullOrEmpty(fname)) {
					BasketUser user = new BasketUser(fmail, "");
					DBManager.delete(user);
				} else {
					BasketUser user = new BasketUser(fmail, fname);
					DBManager.store(user);
				}
			}

			page.setVar("mail", XML.escape(mail));
			page.setVar("fmail", XML.escape(fmail));
			page.setVar("fname", XML.escape(fname));
		}

		{// render month calendars
			Calendar nextMonth = (Calendar) today.clone();
			nextMonth.add(Calendar.MONTH, 1);

			final Map<String, DayRecord> monthMessages = DBManager.getMonthMessages();

			page.setVar("thisMonth", renderCalendar(today, monthMessages, today.get(Calendar.DAY_OF_MONTH), currdate));
			page.setVar("nextMonth", renderCalendar(nextMonth, monthMessages, -1, currdate));
		}

		final List<BasketMessage> messages = DBManager.getDayMessages(DBManager.formatDate(currdate));

		// render day messages
		page.setVar("dayMessages", renderMessageTable(currdate, messages));

		{// ball icon on/off
			boolean on_off = false;
			for (BasketMessage message : messages) {
				if (message.presence && message.ball) {
					on_off = true;
					break;
				}
			}
			page.setVar("ballOnOff", on_off ? "on" : "off");
		}

		page.render(writer);
	}

	static final String[] monthNames = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };

	String renderCalendar(Calendar month, Map<String, DayRecord> monthMessages, int today, Calendar selectedDay) {
		final StringBuilder result = new StringBuilder();
		int i;
		final int weekday;
		{
			Calendar firstDay = (Calendar) month.clone();
			firstDay.set(Calendar.DAY_OF_MONTH, 1);
			weekday = (firstDay.get(Calendar.DAY_OF_WEEK) + 7 - 2) % 7;
		}
		final int intYear = month.get(Calendar.YEAR);
		final int intMonth = 1 + month.get(Calendar.MONTH);
		final int intSelectedMonth = 1 + selectedDay.get(Calendar.MONTH);
		final String strYear = String.valueOf(intYear);
		final String strMonth = String.valueOf(intMonth);

		int selected = (intMonth == intSelectedMonth) ? selectedDay.get(Calendar.DAY_OF_MONTH) : -1;

		result.append("<table width='160' border='0' cellspacing='0' cellpadding='0' class='calendar'>");
		result.append("<tr><td background='/images/bar.png' class='ctitle' >");
		result.append(strYear).append('-').append(monthNames[intMonth]);
		result.append("</td></tr>");

		result.append("<tr><td bgcolor='#EABEAB'><table width='160' border='0' cellspacing='0' cellpadding='0' style='align: center;'>");

		for (i = 0; i < weekday; i++) {
			result.append((i > 4) ? "<td bgcolor='#F0AC8E'>" : "<td>").append("&nbsp;</td>");
		}

		int lastday = month.getActualMaximum(Calendar.DATE);
		for (i = 1; i <= lastday; i++) {
			if ((i + weekday) % 7 == 1)
				result.append("</tr><tr>");

			if (i == selected) {
				result.append("<td bgcolor='#FFFFFF' ");
			} else if (i == today) {
				result.append("<td bgcolor='#DDDDDD' ");
			} else if ((i + weekday + 1) % 7 < 2) {
				result.append("<td bgcolor='#F0AC8E' ");
			} else {
				result.append("<td ");
			}
			result.append("align='right' width=27> ");

			result.append("<a onClick=\"javascript:setdate('").append(strYear).append("','");
			result.append(strMonth).append("','");
			result.append(i).append("');\" ");

			final DayRecord dayRecord = monthMessages.get(DBManager.formatDate(intYear, intMonth, i));
			if (dayRecord != null) {
				result.append("class='cdate");
				result.append(dayRecord.presence > 0 ? '1' : '0');
				result.append(dayRecord.ball ? '1' : '0');
				result.append("' ");
				result.append("onMouseOver=\"return overlib('<b> presence: </b>");
				result.append(dayRecord.presence).append(" of ").append(dayRecord.total);
				result.append("');\" onMouseOut='return nd();' ");
			}
			result.append(">");
			result.append(i);
			result.append("</a></td>");
		}

		for (i = (lastday + weekday) % 7 - 6; i < 1; i++) {
			result.append((i > -2) ? "<td bgcolor='#F0AC8E'>" : "<td>").append("&nbsp;</td>");
		}
		result.append("</tr></table>");
		result.append("</td>");
		result.append("</tr></table>");
		return result.toString();
	}

	private String renderMessageTable(Calendar today, List<BasketMessage> messages) {
		final StringBuilder result = new StringBuilder();

		final int year = today.get(Calendar.YEAR);
		final int month = 1 + today.get(Calendar.MONTH);
		final int day = today.get(Calendar.DAY_OF_MONTH);

		result.append("<table width='98%' border='0' cellspacing='0' cellpadding='0'>");
		result.append("<tr><td bgcolor='#C44F47' class='ctitle' colspan='3'>");
		result.append(year).append(", ").append(monthNames[month]).append(' ').append(day);
		result.append("</td></tr>");

		for (BasketMessage message : messages) {
			final String cellclass = message.presence ? "cell1" : "cell0";
			result.append("<tr><TD class='").append(cellclass).append("'>");
			if (message.ball) {
				result.append("<img src='/images/ball.png'>");
			} else {
				result.append("&nbsp;");
			}
			result.append("<TD class='").append(cellclass).append("' nowrap='nowrap' ><B>");
			result.append(message.username).append("</B>&nbsp;&nbsp;</TD>");

			result.append("<TD class='").append(cellclass).append("' width='80%'>");
			result.append(message.message).append("&nbsp;&nbsp;</TD></tr>");
		}
		result.append("</table>");
		return result.toString();
	}

	private final boolean isNullOrEmpty(String parameter) {
		return parameter == null || parameter.length() <= 0;
	}

}
